#原始感知机学习算法

import random
import numpy as np
import matplotlib.pyplot as plt


def sign(v):
    if v>=0:
        return 1
    else:
        return -1

#感知机学习过程，train_num迭代次数的上限，train_datas训练数据，lr学习率
def train(train_num,train_datas,lr):
    #初始化w和b
    w=[0,0]
    b=0
    for i in range(train_num):
        #任意选取数据点（x,y）
        x=random.choice(train_datas)
        #x1,x2是x的两个维度，y是标签，y=1表示正实例，y=-1表示负实例
        x1,x2,y=x
        if(y*((w[0]*x1+w[1]*x2+b))<=0):
            #w<-w+nyx
            w[0] = w[0] + lr*y*x1
            w[1] = w[1] + lr*y*x2
            #b<-b+ny
            b = b + lr*y
    return w,b

#获得感知机模型的函数表达式
def get_perceptron(w,b):
    return "f(x)=sign("+str(w[0])+"*x1+("+str(w[1])+")*x2+("+str(b)+"))"

#数据及超平面可视化
def plot_points(train_datas,w,b):
    plt.figure()
    if w[1] != 0: # 画直线
        x1 = np.linspace(-5, 5)
        x2 = (-b-w[0]*x1)/w[1]
        plt.plot(x1, x2, color='r', label='y1 data')
    else:
        plt.axvline(x=w[0]) # 画平行于y轴的直线

    datas_len=len(train_datas)
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='o',s=100)
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=100)
    plt.show()


if __name__=='__main__':
    train_data1 = [[3, 3, 1], [4, 3, 1]]  # 正样本
    train_data2 = [[1, 1, -1]]  # 负样本
    train_datas = train_data1 + train_data2  # 样本集
    w,b=train(train_num=50,train_datas=train_datas,lr=0.01)
    print(get_perceptron(w,b))  # 输出函数表达式
    plot_points(train_datas,w,b)